﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WickedFlame.VecDraw.Base.mvvm;
using System.Windows;
using WickedFlame.Util;
using WickedFlame.Core;
using System.Windows.Input;
using WickedFlame.VecDraw.Base.mvvm.commands;
using WickedFlame.VecDraw.Dialog;
using WickedFlame.Util.Actions;
using WickedFlame.Core.Tools;
using System.Windows.Controls;

namespace WickedFlame.VecDraw.viewmodels
{
	public class MainWindowViewModel : BaseViewModel
	{
		public MainWindowViewModel(DependencyObject parent)
			: base(parent)
		{
		}

		#region Commands

		#region Main Menu

		ICommand _newCommand;
		public ICommand NewCommand
		{
			get
			{
				if (_newCommand == null)
					_newCommand = new RelayCommand(OnNew);
				return _newCommand;
			}
		}

		private void OnNew(object param)
		{
			var newdlg = new NewImageDialog
			{
				Owner = Window.GetWindow(Parent),
				WindowStartupLocation = WindowStartupLocation.CenterOwner
			};
			if (newdlg.ShowDialog() == true)
			{
				var service = GetService<ICanvasContainer>();
				service.CreateNewCanvas(newdlg.ImageWidth, newdlg.ImageHeight);
			}
		}

		ICommand _openCommand;
		public ICommand OpenCommand
		{
			get
			{
				if (_openCommand == null)
					_openCommand = new RelayCommand(OnOpen);
				return _openCommand;
			}
		}

		private void OnOpen(object param)
		{
			var action = new ImportFromFileAction();
			action.DoAction(Window.GetWindow(Parent), "");
			if (!action.Error)
			{
				var service = GetService<ICanvasContainer>();
				service.Add(action.Image);

				// register tools to the canvas
				DrawingCanvas.ToolsControler.ToolType = typeof(SelectionTool);
			}
		}

		ICommand _saveCommand;
		public ICommand SaveCommand
		{
			get
			{
				if (_saveCommand == null)
					_saveCommand = new RelayCommand(OnSave, p => SelectedImage != null);
				return _saveCommand;
			}
		}

		private void OnSave(object param)
		{
			using (var dlg = new SaveStatusDialog(Window.GetWindow(Parent)))
			{
				dlg.Show();
				var action = new ExportToFileAction();

				action.DoAction(Window.GetWindow(Parent), SelectedImage, SaveType.Save);
			}
		}

		ICommand _saveAsCommand;
		public ICommand SaveAsCommand
		{
			get
			{
				if (_saveAsCommand == null)
					_saveAsCommand = new RelayCommand(OnSaveAs, p => SelectedImage != null);
				return _saveAsCommand;
			}
		}

		private void OnSaveAs(object param)
		{
			var action = new ExportToFileAction();
			action.DoAction(Window.GetWindow(Parent), SelectedImage, SaveType.SaveAs);
		}

		#endregion

		#region Edit Menu

		ICommand _undoCommand;
		public ICommand UndoCommand
		{
			get
			{
				if (_undoCommand == null)
					_undoCommand = new RelayCommand
						( 
						p => SelectedCanvas.Undo(), 
						p => SelectedCanvas != null && SelectedCanvas.HistoryManager.CanUndo
						);
				return _undoCommand;
			}
		}

		ICommand _redoCommand;
		public ICommand RedoCommand
		{
			get
			{
				if (_redoCommand == null)
					_redoCommand = new RelayCommand
						(
						p => SelectedCanvas.Redo(),
						p => SelectedCanvas != null && SelectedCanvas.HistoryManager.CanRedo
						);
				return _redoCommand;
			}
		}

		ICommand _copyCommand;
		public ICommand CopyCommand
		{
			get
			{
				if (_copyCommand == null)
					_copyCommand = new RelayCommand(OnCopy,
						p => SelectedCanvas != null && (SelectedCanvas.SelectedLayer.ShapeList.SelectionCount > 0 || DrawingCanvas.ToolsControler.ToolType == typeof(HardSelectionTool)));
				return _copyCommand;
			}
		}

		private void OnCopy(object param)
		{
			var rectangle = new Rect(0, 0, 0, 0);

			if (DrawingCanvas.ToolsControler.ToolType == typeof(HardSelectionTool))
			{
				var tool = DrawingCanvas.ToolsControler.SelectedTool as HardSelectionTool;
				if (tool != null && tool.Rectangle.Width > 0)
				{
					rectangle = new Rect((int)tool.Rectangle.X, (int)tool.Rectangle.Y, (int)tool.Rectangle.Width, (int)tool.Rectangle.Height);
				}
			}

			var action = new CopyToClipboardAction();
			action.DoAction(SelectedCanvas, rectangle);
		}

		ICommand _pasteCommand;
		public ICommand PasteCommand
		{
			get
			{
				if (_pasteCommand == null)
					_pasteCommand = new RelayCommand(OnPaste,
						p => SelectedCanvas != null && (Clipboard.ContainsImage() || Clipboard.ContainsData("vectorshapes")));
				return _pasteCommand;
			}
		}

		private void OnPaste(object param)
		{
			if (Clipboard.ContainsImage())
			{
				try
				{
					var action = new PasteAction();
					action.DoAction(SelectedCanvas);

					// ask to resize the canvas if the pasted image is biger than the curent canvas
					if (action.Image.Width > SelectedCanvas.Width || action.Image.Height > SelectedCanvas.Height)
					{
						var dlg = new ImageCanvasSizeDialog
						{
							Owner = Window.GetWindow(Parent),
							Image = action.Image,
							WindowStartupLocation = WindowStartupLocation.CenterOwner
						};

						if (dlg.ShowDialog() == true)
						{
							if (dlg.ImageInsertDialogResult == ImageInsertDialogResult.Resize)
							{
								double w = action.Image.Width;
								if (w < SelectedCanvas.Width)
									w = SelectedCanvas.Width;

								double h = action.Image.Height;
								if (h < SelectedCanvas.Height)
									h = SelectedCanvas.Height;

								var service = GetService<ICanvasContainer>();
								service.ResizeCanvas(w, h);
							}
						}
						else
							return;
					}

					action.FinalizeAction();
				}
				catch
				{
					//layer is not selectable or is not visible
				}
			}
			else
				MessageBox.Show("There is no image contained in the Clipboard");
		}

		ICommand _cutCommand;
		public ICommand CutCommand
		{
			get
			{
				if (_cutCommand == null)
					_cutCommand = new RelayCommand(OnCut,
						p => SelectedCanvas != null && (SelectedCanvas.SelectedLayer.ShapeList.SelectionCount > 0 || DrawingCanvas.ToolsControler.ToolType == typeof(HardSelectionTool)));
				return _cutCommand;
			}
		}

		private void OnCut(object param)
		{
			var rectangle = new Rect(0, 0, 0, 0);

			if (DrawingCanvas.ToolsControler.ToolType == typeof(HardSelectionTool))
			{
				var tool = DrawingCanvas.ToolsControler.SelectedTool as HardSelectionTool;
				if (tool != null && tool.Rectangle.Width > 0)
				{
					rectangle = new Rect((int)tool.Rectangle.X, (int)tool.Rectangle.Y, (int)tool.Rectangle.Width, (int)tool.Rectangle.Height);
				}
			}

			var action = new CutAction();
			action.DoAction(SelectedCanvas, rectangle, true);
		}

		ICommand _selectAllCommand;
		public ICommand SelectAllCommand
		{
			get
			{
				if (_selectAllCommand == null)
					_selectAllCommand = new RelayCommand
						(
						p =>
						{
							DrawingCanvas.ToolsControler.ToolType = typeof(SelectionTool);
							SelectedCanvas.SelectedLayer.ShapeList.SelectAll();
						}, 
						p => SelectedCanvas != null
						);
				return _selectAllCommand;
			}
		}

		ICommand _unselectAllCommand;
		public ICommand UnselectAllCommand
		{
			get
			{
				if (_unselectAllCommand == null)
					_unselectAllCommand = new RelayCommand
						(
						p => SelectedCanvas.SelectedLayer.ShapeList.UnselectAll(),
						p => SelectedCanvas != null
						);
				return _unselectAllCommand;
			}
		}

		ICommand _deleteCommand;
		public ICommand DeleteCommand
		{
			get
			{
				if (_deleteCommand == null)
					_deleteCommand = new RelayCommand(OnDelete, p => SelectedCanvas != null);
				return _deleteCommand;
			}
		}

		private void OnDelete(object param)
		{
			// remove all selected shapes
			var del = new DeleteAction();
			del.DeleteSelection(SelectedCanvas);

			if (DrawingCanvas.ToolsControler.ToolType == typeof(HardSelectionTool))
			{
				var tool = DrawingCanvas.ToolsControler.SelectedTool as HardSelectionTool;
				if (tool != null && tool.Rectangle.Width > 0)
				{
					var action = new CutAction();
					action.DoAction((SelectedCanvas),
						new Rect((int)tool.Rectangle.X, (int)tool.Rectangle.Y, (int)tool.Rectangle.Width, (int)tool.Rectangle.Height),
						false);
				}
			}
		}

		#endregion

		#region View Menu

		ICommand _zoomInCommand;
		public ICommand ZoomInCommand
		{
			get
			{
				if (_zoomInCommand == null)
					_zoomInCommand = new RelayCommand(OnZoomIn, p => SelectedCanvas != null);
				return _zoomInCommand;
			}
		}

		private void OnZoomIn(object param)
		{
			var service = GetService<ICanvasContainer>();
			service.ZoomIn(10);
		}

		ICommand _zoomOutCommand;
		public ICommand ZoomOutCommand
		{
			get
			{
				if (_zoomOutCommand == null)
					_zoomOutCommand = new RelayCommand(OnZoomOut, p => SelectedCanvas != null);
				return _zoomOutCommand;
			}
		}

		private void OnZoomOut(object param)
		{
			var service = GetService<ICanvasContainer>();
			service.ZoomOut(10);
		}

		ICommand _showGridCommand;
		public ICommand ShowGridCommand
		{
			get
			{
				if (_showGridCommand == null)
					_showGridCommand = new RelayCommand<MenuItem>(OnShowGrid, p => SelectedCanvas != null);
				return _showGridCommand;
			}
		}

		private void OnShowGrid(MenuItem param)
		{
			DrawingCanvas.ShowGrid = !DrawingCanvas.ShowGrid;
			if (param != null)
				param.IsChecked = DrawingCanvas.ShowGrid;
		}

		ICommand _snapToTrackerCommand;
		public ICommand SnapToTrackerCommand
		{
			get
			{
				if (_snapToTrackerCommand == null)
					_snapToTrackerCommand = new RelayCommand<MenuItem>(OnSnapToTracker, p => SelectedCanvas != null);
				return _snapToTrackerCommand;
			}
		}

		private void OnSnapToTracker(MenuItem param)
		{
			//SnapToTrackers = !SnapToTrackers;
			//if (param != null)
			//    param.IsChecked = ShapePropertySettings.Settings.SnapToTrackers;
		}
		
		#endregion

		#region View Menu

		ICommand _addLayerCommand;
		public ICommand AddLayerCommand
		{
			get
			{
				if (_addLayerCommand == null)
					_addLayerCommand = new RelayCommand(OnAddLayer, p => SelectedCanvas != null);
				return _addLayerCommand;
			}
		}

		private void OnAddLayer(object param)
		{
			var service = GetService<ICanvasContainer>();
			service.ZoomIn(10);
		}

		#endregion

		#endregion

		#region Properties

		DrawingCanvas _selectedCanvas;
		public DrawingCanvas SelectedCanvas
		{
			get { return _selectedCanvas; }
			set
			{
				_selectedCanvas = value;
				RaisePropertyChanged("SelectedCanvas");
			}
		}

		VectorImage _selectedImage;
		public VectorImage SelectedImage
		{
			get { return _selectedImage; }
			set
			{
				_selectedImage = value;
				RaisePropertyChanged("SelectedImage");
			}
		}

		#region Menu Properties

		public bool SnapToTrackers
		{
			get
			{
				return ShapePropertySettings.Settings.SnapToTrackers;
			}
			set
			{
				ShapePropertySettings.Settings.SnapToTrackers = value;
				RaisePropertyChanged("SnapToTrackers");
			}
		}

		#endregion

		#region Footer Properties

		string _pageSize;
		public string PageSize
		{
			get { return _pageSize; }
			set
			{
				_pageSize = value;
				RaisePropertyChanged("PageSize");
			}
		}

		string _mousePosition;
		public string MousePosition
		{
			get { return _mousePosition; }
			set
			{
				_mousePosition = value;
				RaisePropertyChanged("MousePosition");
			}
		}

		public string Version
		{
			get
			{
				return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
			}
		}

		#endregion

		#endregion
	}
}
